package com.mocha.nezha.nezha;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.mocha.common.kits.MapKits;
import com.mocha.nezha.dmo.entity.CameraPGEntity;
import com.mxgraph.layout.mxCircleLayout;
import com.mxgraph.layout.mxIGraphLayout;
import com.mxgraph.util.mxCellRenderer;
import lombok.Getter;
import org.jgrapht.alg.shortestpath.BFSShortestPath;
import org.jgrapht.ext.JGraphXAdapter;
import org.jgrapht.graph.SimpleGraph;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.List;

/**
 * @author songkui
 * @since 2024/3/19 16:04
 */

@Getter
public class ParkPoleGraph {

    private SimpleGraph<PoleVertex, PoleEdge> poleGraph = null;
    private   Map<String, PoleVertex> poleMap = null;  //key PoleCode
    private   String pakCode;

    private Map<String, CameraPGEntity> cameraMap = null;  // key: cameraCode;  v: camera;

    public ParkPoleGraph(){
    }

    // 如果需要修改； 则需要重新初始化
    public void initializePoleGraph(String parkCode, List<PoleVertex> poleList, List<PoleEdge> poleEdgeList, Map<String, CameraPGEntity> cmap) throws Exception {
        pakCode = parkCode;
        poleGraph = new SimpleGraph<>(PoleEdge.class);
        cameraMap = cmap;

        if (CollectionUtil.isEmpty(poleList) || CollectionUtil.isEmpty(poleEdgeList)) {
            throw new Exception("Initialize pole graph  data is incomplete");
        }

        poleMap = new HashMap<>(MapKits.mapSize(poleList.size()));
        for (PoleVertex vertex : poleList) {
            poleGraph.addVertex(vertex);
            poleMap.put(vertex.getPoleCode(), vertex);
        }

        for (PoleEdge edge : poleEdgeList) {
            PoleVertex source = poleMap.get(edge.getSourcePoleCode());
            PoleVertex target = poleMap.get(edge.getTargetPoleCode());
            if (null == source || null == target) {
                throw new Exception("Initialize camera graph  edge  source  or target is null");
            }
            poleGraph.addEdge(source, target, edge);

        }

        Set<PoleVertex> vertexSet = poleGraph.vertexSet();
        if (CollectionUtil.isEmpty(vertexSet)){
            throw new Exception("Initialize camera graph vertexSet  is null");
        }

        for (PoleVertex vertex : vertexSet){
            vertex.setFork(isFork(vertex));
        }

    }

    public void updateCamera(Map<String, CameraPGEntity> map){
        cameraMap = map;
    }


    private boolean isFork(PoleVertex vertex){
       int outSize =  poleGraph.outDegreeOf(vertex);
        return outSize < 3 ? false : true;
    }




    //当前节点 边
    public Set<PoleEdge> findEdgeByCurrent(String currentPoleCode){
       return poleGraph.outgoingEdgesOf(poleMap.get(currentPoleCode));
    }


    //最少节点
    public   List<PoleVertex> findVertexPaths(PoleVertex start, PoleVertex end) {
        BFSShortestPath<PoleVertex, PoleEdge> alg = new BFSShortestPath<>(poleGraph);
        return alg.getPath(start, end).getVertexList();
    }

    //最短边
    public  List<PoleEdge> findEdgePaths(PoleVertex start, PoleVertex end) {
        BFSShortestPath<PoleVertex, PoleEdge> alg = new BFSShortestPath<>(poleGraph);
        return alg.getPath(start, end).getEdgeList();
    }


    //导出图片
    public void buildImage() throws IOException {
        JGraphXAdapter<PoleVertex, PoleEdge> graphAdapter = new JGraphXAdapter<>(poleGraph);
        mxIGraphLayout layout = new mxCircleLayout(graphAdapter);
        layout.execute(graphAdapter.getDefaultParent());

        BufferedImage image = mxCellRenderer.createBufferedImage(graphAdapter, null, 2, Color.WHITE, true, null);
        File imgFile = new File("D:/graph2.png");
        ImageIO.write(image, "PNG", imgFile);
    }

    public PoleVertex getPoleVertexByCameraCode(String cameraCode){
        CameraPGEntity entity = cameraMap.get(cameraCode);
        return null == entity || StrUtil.isEmpty(entity.getPoleCode()) ? null : poleMap.get(entity.getPoleCode());
    }

    public PoleVertex getPoleVertexByPoleCode(String poleCode){
        return poleMap.get(poleCode);
    }



}
